package com.yhq.basic.thread.juc;

import com.yhq.basic.thread.po.MyEntry;
import lombok.SneakyThrows;
import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * CAS(Compare And Swap) ，不会存在上下文切换，它是CPU硬件层面的一种指令，无锁实现变量同步
 * 多处理器则加Lock 前缀
 * 应用场景：JUC(atomic,AQS,util)
 * 缺点：1.自旋CAS长时间不成功，则会给CPU带来非常大的开销；2.只能保证一个共享变量原子操作；3.ABA问题：是因为根据值来比较，解决ABA问题，使用版本号比较
 *
 * @author hqyin
 * @date 2025/5/6 4:56 AM
 */
public class TestCAS {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        //CAS使用，使用UnSafe
//        test_CASUse();
        //使用UnSafe自增
//        test_CASIncrement();
        //ABA问题
        //解决ABA问题 AtomicStampedReference
        //test_AtomicInteger  getXX 返回旧值，add或update返回新值
        test_AtomicInteger();



    }

    public int cnt = 0;
    @SneakyThrows
    private static void test_CASIncrement() {
        //获取Unsafe对象
        Field field = Unsafe.class.getDeclaredField("theUnsafe");
        field.setAccessible(true);
        Unsafe unsafe = (Unsafe) field.get(null);

        //获取对象属性偏移量
        TestCAS test = new TestCAS();
        long offset = unsafe.objectFieldOffset(TestCAS.class.getField("cnt"));

        for (int i = 0; i < 3; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int j = 0; j < 10; j++) {
                        boolean b = unsafe.compareAndSwapInt(test,offset,test.cnt,test.cnt+1);
                        if(b) {
                            System.out.println(test.cnt);
                        }
                    }
                }
            }).start();
        }


        Thread.sleep(1000);
        System.out.println("最终结果："+test.cnt);

    }

    //    static int count = 0;
      static AtomicInteger count = new AtomicInteger(0);
    private static void test_AtomicInteger() {

        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    //每个线程增加20
                    for (int j = 0; j < 10; j++) {
//                        count++;
                        count.incrementAndGet();
                    }

                }
            });
            thread.start();
        }
        System.out.println(count);
    }

    private static void test_CASUse() throws NoSuchFieldException, IllegalAccessException {
        //获取UnSafe对象
        Field field = Unsafe.class.getDeclaredField("theUnsafe");
        field.setAccessible(true);
        Unsafe unsafe = (Unsafe) field.get(null);
        System.out.println(unsafe);
        //获取对象的偏移量
        MyEntry myEntry = new MyEntry();
        System.out.println("交换前："+myEntry.x);
        long offset = unsafe.objectFieldOffset(myEntry.getClass().getField("x"));
        //比较与交换
        //对象，属性偏移量，旧值，新值
        boolean oneSuccess = unsafe.compareAndSwapObject(myEntry,offset,null,"你好");
        System.out.println("交换1次，是否成功："+oneSuccess+",结果："+myEntry.x);
        boolean twoSuccess = unsafe.compareAndSwapObject(myEntry,offset,"你好","借点钱");
        System.out.println("交换2次，是否成功："+twoSuccess+",结果："+myEntry.x);
        boolean threeSuccess = unsafe.compareAndSwapObject(myEntry,offset,null,"hello");
        System.out.println("交换3次，是否成功："+threeSuccess+",结果："+myEntry.x);
    }
}


